<!DOCTYPE html>

<head>
  <title>参考自灰大教程</title>
  <meta http-equiv="content-type" content="text/html" charset="UTF-8">
  <link rel="stylesheet" href="../common.css">
  <style type="text/css">
    body,
    html {
      background: #000f14;
    }

    .container {
      position: relative;
      width: 400px;
      height: 400px;
    }

    .putPie {
      position: absolute;
      top: 0;
      left: 0;
      width: 400px;
      height: 400px;
      z-index: 3;
    }

    .lizi {
      position: absolute;
      top: 158px;
      left: 60px;
      z-index: 2;
      width: 280px;
      height: 132px;
      background: url(../img/guang.png) no-repeat 0px 0px;
      animation: rotate 1s infinite steps(35, end);
    }

  
    @keyframes rotate {
      0% {
        background-position-y: 0px;
      }

      100% {
        background-position-y: -4620px;
      }
    }

    svg text.percent {
      fill: #fff;
      text-anchor: middle;
      font-size: 14px;
    }

    .light {
      width: 400px;
      height: 400px;
      background: url(../img/light.png) no-repeat center 135px;
      position: absolute;
      top: 0;
      left: 0;
    }
  </style>
</head>

<body>
  <div class="rowFlex">
    <div class="container">
      <div id="putPie" class="putPie"></div>
      <div class="lizi"></div>
      <div class="light"></div>
    </div>
  </div>

  <script type="text/javascript" src="http://d3js.org/d3.v3.min.js"></script>
  <script>
    ! function() {
      var Donut3D = {};

      function pieTop(d, rx, ry, ir) {
        if (d.endAngle - d.startAngle == 0) return "M 0 0";
        var sx = rx * Math.cos(d.startAngle),
          sy = ry * Math.sin(d.startAngle),
          ex = rx * Math.cos(d.endAngle),
          ey = ry * Math.sin(d.endAngle);

        var ret = [];
        ret.push("M", sx, sy, "A", rx, ry, "0", (d.endAngle - d.startAngle > Math.PI ? 1 : 0), "1", ex, ey, "L", ir * ex, ir * ey);
        ret.push("A", ir * rx, ir * ry, "0", (d.endAngle - d.startAngle > Math.PI ? 1 : 0), "0", ir * sx, ir * sy, "z");
        return ret.join(" ");
      }

      function pieOuter(d, rx, ry, h) {
        var startAngle = (d.startAngle > Math.PI ? Math.PI : d.startAngle);
        var endAngle = (d.endAngle > Math.PI ? Math.PI : d.endAngle);

        var sx = rx * Math.cos(startAngle),
          sy = ry * Math.sin(startAngle),
          ex = rx * Math.cos(endAngle),
          ey = ry * Math.sin(endAngle);

        var ret = [];
        ret.push("M", sx, h + sy, "A", rx, ry, "0 0 1", ex, h + ey, "L", ex, ey, "A", rx, ry, "0 0 0", sx, sy, "z");
        return ret.join(" ");
      }

      function pieInner(d, rx, ry, h, ir) {
        var startAngle = (d.startAngle < Math.PI ? Math.PI : d.startAngle);
        var endAngle = (d.endAngle < Math.PI ? Math.PI : d.endAngle);

        var sx = ir * rx * Math.cos(startAngle),
          sy = ir * ry * Math.sin(startAngle),
          ex = ir * rx * Math.cos(endAngle),
          ey = ir * ry * Math.sin(endAngle);

        var ret = [];
        ret.push("M", sx, sy, "A", ir * rx, ir * ry, "0 0 1", ex, ey, "L", ex, h + ey, "A", ir * rx, ir * ry, "0 0 0", sx, h + sy, "z");
        return ret.join(" ");
      }

      function getPercent(d) {
        return (d.endAngle - d.startAngle > 0.2 ?
          Math.round(1000 * (d.endAngle - d.startAngle) / (Math.PI * 2)) / 10 + '%' : '');
      }

      Donut3D.transition = function(id, data, rx, ry, h, ir) {
        function arcTweenInner(a) {
          var i = d3.interpolate(this._current, a);
          this._current = i(0);
          return function(t) {
            return pieInner(i(t), rx + 0.5, ry + 0.5, h, ir);
          };
        }

        function arcTweenTop(a) {
          var i = d3.interpolate(this._current, a);
          this._current = i(0);
          return function(t) {
            return pieTop(i(t), rx, ry, ir);
          };
        }

        function arcTweenOuter(a) {
          var i = d3.interpolate(this._current, a);
          this._current = i(0);
          return function(t) {
            return pieOuter(i(t), rx - .5, ry - .5, h);
          };
        }

        function textTweenX(a) {
          var i = d3.interpolate(this._current, a);
          this._current = i(0);
          return function(t) {
            return 0.6 * rx * Math.cos(0.5 * (i(t).startAngle + i(t).endAngle));
          };
        }

        function textTweenY(a) {
          var i = d3.interpolate(this._current, a);
          this._current = i(0);
          return function(t) {
            return 0.6 * rx * Math.sin(0.5 * (i(t).startAngle + i(t).endAngle));
          };
        }

        var _data = d3.layout.pie().sort(null).value(function(d) {
          return d.value;
        })(data);

        d3.select("#" + id).selectAll(".innerSlice").data(_data)
          .transition().duration(750).attrTween("d", arcTweenInner);

        d3.select("#" + id).selectAll(".topSlice").data(_data)
          .transition().duration(750).attrTween("d", arcTweenTop);

        d3.select("#" + id).selectAll(".outerSlice").data(_data)
          .transition().duration(750).attrTween("d", arcTweenOuter);

        d3.select("#" + id).selectAll(".percent").data(_data).transition().duration(750)
          .attrTween("x", textTweenX).attrTween("y", textTweenY).text(getPercent);
      }

      Donut3D.draw = function(id, data, x /*center x*/ , y /*center y*/ ,
        rx /*radius x*/ , ry /*radius y*/ , h /*height*/ , ir /*inner radius*/ ) {

        var _data = d3.layout.pie().sort(null).value(function(d) {
          return d.value;
        })(data);

        var slices = d3.select("#" + id).append("g").attr("transform", "translate(" + x + "," + y + ")")
          .attr("class", "slices");

        slices.selectAll(".innerSlice").data(_data).enter().append("path").attr("class", "innerSlice")
          .style("fill", function(d) {
            return d3.hsl(d.data.color).darker(0.7);
          })
          .attr("d", function(d) {
            return pieInner(d, rx + 0.5, ry + 0.5, h, ir);
          })
          .each(function(d) {
            this._current = d;
          });

        slices.selectAll(".topSlice").data(_data).enter().append("path").attr("class", "topSlice")
          .style("fill", function(d) {
            return d.data.color;
          })
          .style("stroke", function(d) {
            return d.data.color;
          })
          .attr("d", function(d) {
            return pieTop(d, rx, ry, ir);
          })
          .each(function(d) {
            this._current = d;
          });

        slices.selectAll(".outerSlice").data(_data).enter().append("path").attr("class", "outerSlice")
          .style("fill", function(d) {
            return d3.hsl(d.data.color).darker(0.7);
          })
          .attr("d", function(d) {
            return pieOuter(d, rx - .5, ry - .5, h);
          })
          .each(function(d) {
            this._current = d;
          });

        slices.selectAll(".percent").data(_data).enter().append("text").attr("class", "percent")
          .attr("x", function(d) {
            return 0.6 * rx * Math.cos(0.5 * (d.startAngle + d.endAngle));
          })
          .attr("y", function(d) {
            return 0.6 * ry * Math.sin(0.5 * (d.startAngle + d.endAngle));
          })
          .text(getPercent).each(function(d) {
            this._current = d;
          });
      }

      this.Donut3D = Donut3D;
    }();
  </script>
  <script type="text/javascript">
    var data = [{
        label: "a1",
        color: "#d7de4d",
        value: 122
      },
      {
        label: "a2",
        color: "#008ee0",
        value: 244
      },
      {
        label: "a3",
        color: "#24d0ff",
        value: 300
      },
      {
        label: "a4",
        color: "#03dea3",
        value: 96
      }
    ];

    var svg = d3.select("#putPie").append("svg").attr("width", 400).attr("height", 400);
    svg.append("g").attr("id", "demoPie");
    Donut3D.draw("demoPie", data, 200, 200, 112, 50, 20, 0.8);


    function changeData() {
      let newData = randomData();
      Donut3D.transition("demoPie", newData, 112, 50, 20, 0.8);
    }

    function randomData() {
      return data.map(function(d) {
        return {
          label: d.label,
          value: Math.ceil(1000 * Math.random()),
          color: d.color
        };
      });
    }

    setInterval(() => {
      changeData();
    }, 4000);
  </script>
</body>

</html>